package com.dkm.util.qiniu;

import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.BatchStatus;
import com.qiniu.util.Auth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;

/**
 * 七牛上传工具类
 * @author  chenhw
 */
@Component
public class QiNiuUtil {

	private static Logger logger = LoggerFactory.getLogger(QiNiuUtil.class);

	private  static String ACCESSKEY;
	private  static String SECRETKEY;
	private  static String BUCKET_IMG;

	@Value("${QiNiu-ACCESSKEY}")
	public  void setACCESSKEY(String ACCESSKEY) {
		this.ACCESSKEY = ACCESSKEY;
	}

	@Value("${QiNiu-SECRETKEY}")
	public void setSECRETKEY(String SECRETKEY) {
		this.SECRETKEY = SECRETKEY;
	}

	@Value("${QiNiu-BUCKET_IMG}")
	public void setBUCKET_IMG(String BUCKET_IMG) {
		this.BUCKET_IMG = BUCKET_IMG;
	}


	private final static String BUCKET_VIDEO = "videotest";
	private final static String BUCKET_TRAINING = "training";



	private QiNiuUtil(){}

	private static final QiNiuUtil qiNiuUtil = new QiNiuUtil();

	public static QiNiuUtil getInstance(){
		return qiNiuUtil;
	}


	/**
	 * 上传图片资源
	 * @param obj 图片的数据流
	 * @param fileName 文件名
	 * @return 1：上传成功 0：失败
	 */
	public int uploadFile(Object obj,String fileName){
		return uploadFile(obj,fileName,BUCKET_IMG);
	}

	/**
	 * 上传视频到七牛服务器
	 * @param obj	上传的视频资源
	 * @param fileName	文件名称（按业务规则生成文件名。需带拓展名）
	 * @return	1：上传成功 0：失败
	 */
	public int uploadVideo(Object obj,String fileName){
		return uploadFile(obj,fileName, BUCKET_VIDEO);
	}


	/**
	 * 上传实训平台文件到七牛服务器
	 * @param obj	上传的视频资源
	 * @param fileName	文件名称（按业务规则生成文件名。需带拓展名）
	 * @return	1：上传成功 0：失败
	 */
	public int uploadTrainingFile(Object obj,String fileName){
		return uploadFile(obj,fileName, BUCKET_TRAINING);
	}

	/**
	 * 上传实训平台文件到七牛服务器
	 * @param inputStream  文件流
	 * @param fileName	文件名称（按业务规则生成文件名。需带拓展名）
	 * @return	1：上传成功 0：失败
	 */
	public int uploadTrainingInputStream(InputStream inputStream, String fileName){
		return uploadInputStream(inputStream, fileName, BUCKET_TRAINING);
	}

	/**
	 * 上传文件到七牛服务器
	 * @param obj	支持上传类型1.File文件  2.InputStream 3.图片路径 4.视频
	 * @param fileName	文件名称（按业务规则生成文件名。需带拓展名）
	 * @param bucket 存储空间
	 * @return	1：上传成功 0：失败
	 */
	private int uploadFile(Object obj,String fileName,String bucket){
		//构造一个带指定Zone对象的配置类
		Configuration cfg = new Configuration(Zone.huanan());
		//...其他参数参考类注释
		UploadManager uploadManager = new UploadManager(cfg);
		//...生成上传凭证，然后准备上传
		Auth auth = Auth.create(ACCESSKEY, SECRETKEY);
		String upToken = auth.uploadToken(bucket);
		try {
			Response response = null;
			if(obj instanceof File){
				response = uploadManager.put((File)obj, fileName, upToken);
			}else if(obj instanceof String){
				response = uploadManager.put((String)obj, fileName, upToken);
			}else if(obj instanceof InputStream){
				InputStream inStream = (InputStream)obj;
				ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
				//buff用于存放循环读取的临时数据
				byte[] buff = new byte[100];
				int rc = 0;
				while ((rc = inStream.read(buff, 0, 100)) > 0) {
					swapStream.write(buff, 0, rc);
				}
				//in_b为转换之后的结果
				byte[] imgByte = swapStream.toByteArray();
				response = uploadManager.put(imgByte, fileName, upToken);
			}else{
				return -1;
			}

			//解析上传成功的结果
			if(response.statusCode == 200){
				System.out.println("upload success");
				return 1;
			}else{
				System.out.println("upload filed");
				return 0;
			}
		} catch (QiniuException ex) {
			Response r = ex.response;
			System.err.println(r.toString());
			try {
				System.err.println(r.bodyString());
			} catch (QiniuException ex2) {
				//ignore
			}
			return 0;
		} catch (Exception e) {
			System.err.println("上传失败");
			return 0;
		}
	}

	/**
	 * 上传文件到七牛服务器
	 * @param inputStream  文件流
	 * @param fileName 文件名称（按业务规则生成文件名。需带拓展名）
	 * @param bucket 存储空间
	 * @return 1：上传成功 0：失败
	 */
	private int uploadInputStream(InputStream inputStream, String fileName, String bucket){
		//构造一个带指定Zone对象的配置类  设置区域
		Configuration cfg = new Configuration(Zone.zone2());

		//...其他参数参考类注释
		UploadManager uploadManager = new UploadManager(cfg);
		//...生成上传凭证，然后准备上传
		Auth auth = Auth.create(ACCESSKEY, SECRETKEY);
		String upToken = auth.uploadToken(bucket);
		try {
			// 文件流上传
			Response response = uploadManager.put(inputStream, fileName, upToken, null, null);

			//解析上传成功的结果
			if(response.statusCode == 200){
				logger.info("upload success");
				return 1;
			}else{
				logger.info("upload filed");
				return 0;
			}
		} catch (QiniuException ex) {
			logger.error("QiniuException fileName: {}", fileName);
			logger.error("QiniuException exception", ex);
			logger.error("QiniuException response {}", ex.response);
			logger.error("QiniuException error {}", ex.error());
			return 0;
		} catch (Exception e) {
			logger.error("upload filed fileName: {}, exception: {}", fileName, e);
			return 0;
		}
	}

	/**
	 * 批量删除七牛服务器文件 目前就删除图片空间的
	 * @param fileNames	string数组 传入文件名即可
	 */
	public void delFiles(String[] fileNames){

		//构造一个带指定Zone对象的配置类
		Configuration cfg = new Configuration(Zone.zone0());
		//...其他参数参考类注释
		Auth auth = Auth.create(ACCESSKEY, SECRETKEY);
		BucketManager bucketManager = new BucketManager(auth, cfg);
		try {
			//单次批量请求的文件数量不得超过1000
			BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
			batchOperations.addDeleteOp(BUCKET_IMG, fileNames);
			Response response = bucketManager.batch(batchOperations);
			BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class);
			for (int i = 0; i < fileNames.length; i++) {
				BatchStatus status = batchStatusList[i];
				String key = fileNames[i];
				System.out.print(key + "\t");
				if (status.code == 200) {
					System.out.println("delete success");
				} else {
					System.out.println(status.data.error);
				}
			}
		} catch (QiniuException ex) {
			System.err.println(ex.response.toString());
		}

	}

}